www.gusucode.com > VC++ 三维图形生成和察看工具 > VC++ 三维图形生成和察看工具/code/mesh/Lib3D/ParserVrml.cpp

    //Download by http://www.NewXing.com
//********************************************
// ParserVrml.cpp
// class CParserVrml
//********************************************
// alliez@usc.edu
// Created : 02/04/98
// Modified : 02/04/98
//********************************************

#include "stdafx.h"
#include "Base3d.h"
#include "ParserVrml.h"

//********************************************
// Constructor
//********************************************
CParserVrml::CParserVrml()
{
	m_pBuffer = NULL;
	m_pBufferWord[0] = '\0';
	m_pBufferLine[0] = '\0';
	m_IndexBuffer = 0;
}

//********************************************
// Destructor
//********************************************
CParserVrml::~CParserVrml()
{
	Free();
}

//********************************************
// Destructor
//********************************************
void CParserVrml::Free(void)
{
	if(m_pBuffer != NULL)
		delete [] m_pBuffer;
	m_IndexBuffer = 0;
}

//********************************************
// Run
//********************************************
int CParserVrml::Run(char *filename,
										 CSceneGraph3d *pSceneGraph)
{
	TRACE("\n");
	TRACE("Start vrml parser\n");
	TRACE("  file : %s\n",filename);

	// Free
	TRACE("  free...");
	Free();
	TRACE("ok\n");

	// ReadFile
	if(!ReadFile(filename))
		return 0;

	// CheckVersion
	if(!CheckVersion())
		return 0;

	CountDef();
	CountMesh();

	while(OffsetToStringBeginLine("DEF"))
		ReadMesh(pSceneGraph);

	TRACE("End vrml parser\n");
	TRACE("\n");
	return 1;
}


//********************************************
// ReadFile
//********************************************
int CParserVrml::ReadFile(char *filename)
{
	m_FileName = filename;

	CFile file;
	CFileException ex;

	// Opening
	TRACE("  opening...");
	if(!file.Open(filename, CFile::modeRead | CFile::typeBinary,&ex))
	{
		#ifdef _DEBUG
		  afxDump << "File could not be opened " << ex.m_cause << "\n";
		#endif
		TRACE("unable to open file for reading\n");
		return 0;
	}
	TRACE("ok\n");

	// Size file
	m_SizeFile = file.GetLength();
	TRACE("  length : %d bytes\n",m_SizeFile);

	// Alloc
	TRACE("  alloc...");
	m_pBuffer = new char[m_SizeFile];
	if(m_pBuffer == NULL)
	{
		TRACE("insuffisant memory\n");
		return 0;
	}
	TRACE("ok\n");

	// Reading
	TRACE("  reading...");
	TRY
	{
		file.Read(m_pBuffer,m_SizeFile);
	}
	CATCH(CFileException, e)
	{
		#ifdef _DEBUG
				afxDump << "Error during reading " << e->m_cause << "\n";
		#endif
		TRACE("error during reading\n");
		file.Close();
		return 0;
	}
	END_CATCH
	TRACE("ok\n");

	// Closing
	file.Close();

	return 1;
}

//********************************************
// ReadLine
// eol : '\n'
// eos : '\0'
//********************************************
int CParserVrml::ReadLine()
{
	m_pBufferLine[0] = '\0';
	int i=0;
	do
		m_pBufferLine[i++] = m_pBuffer[m_IndexBuffer++];
	while(m_pBuffer[m_IndexBuffer-1] != '\n' && 
		    i < MAX_LINE_VRML &&
				m_IndexBuffer < m_SizeFile);

	m_pBufferLine[i-1] = '\0';

	//TRACE("  line : %s\n",m_pBufferLine);

	return 1;
}


//********************************************
// ReadLine
// eol : '\n'
// eos : '\0'
//********************************************
int CParserVrml::ReadWord()
{
	m_pBufferWord[0] = '\0';
	int i=0;

	// Jump to next valid character
	while((m_pBuffer[m_IndexBuffer] == '\n' || 
		     m_pBuffer[m_IndexBuffer] == '\t' || 
		     m_pBuffer[m_IndexBuffer] == '\r' || 
		     m_pBuffer[m_IndexBuffer] == ' ') &&
				 m_IndexBuffer < m_SizeFile)
		m_IndexBuffer++;

	// Check eof
	if(m_IndexBuffer >= m_SizeFile)
		return 0;

	do
		m_pBufferWord[i++] = m_pBuffer[m_IndexBuffer++];
	while(m_pBuffer[m_IndexBuffer-1] != '\n' && 
		    m_pBuffer[m_IndexBuffer-1] != '\t' && 
		    m_pBuffer[m_IndexBuffer-1] != '\r' && 
		    m_pBuffer[m_IndexBuffer-1] != ' ' && 
		    i < MAX_WORD_VRML &&
				m_IndexBuffer < m_SizeFile);

	m_pBufferWord[i-1] = '\0';

	//TRACE("  word : %s\n",m_pBufferWord);

	return 1;
}




//********************************************
// CheckVersion
//********************************************
int CParserVrml::CheckVersion()
{
	ReadLine();
	TRACE("  check version (vrml 2.0)...");
	if(strstr(m_pBufferLine,"#VRML V2.0") != NULL)
	{
		TRACE("ok\n");
		return 1;
	}
	TRACE("invalid\n");
	return 0;
}



//********************************************
// CountDef
//********************************************
void CParserVrml::CountDef(void)
{
	int tmp = m_IndexBuffer;
	int nb = 0;
	while(m_IndexBuffer < m_SizeFile)
	{
		ReadLine();
		if(strncmp(m_pBufferLine,"DEF",3) == 0)
			nb++;
	}
	TRACE("  %d objects\n",nb);
	m_IndexBuffer = tmp;
}

//********************************************
// CountMesh
//********************************************
int CParserVrml::CountMesh(void)
{
	int tmp = m_IndexBuffer;
	int nb = 0;
	while(m_IndexBuffer < m_SizeFile)
	{
		ReadLine();
		if(strstr(m_pBufferLine,"IndexedFaceSet") != NULL)
			nb++;
	}
	TRACE("  %d meshes\n",nb);
	m_IndexBuffer = tmp;
	return nb;
}

//********************************************
// OffsetToStringBeginLine
//********************************************
int CParserVrml::OffsetToStringBeginLine(char *string)
{
	while(m_IndexBuffer < m_SizeFile)
	{
		ReadLine();
		if(strncmp(m_pBufferLine,string,strlen(string)) == 0)
		{
			m_IndexBuffer -= strlen(m_pBufferLine)+1;
			/*
			TRACE("  begin line : %c%c%c%c%c...\n",m_pBuffer[m_IndexBuffer],
				                                     m_pBuffer[m_IndexBuffer+1],
				                                     m_pBuffer[m_IndexBuffer+2],
				                                     m_pBuffer[m_IndexBuffer+3],
																				     m_pBuffer[m_IndexBuffer+4]);*/
			return 1;
		}
	}
	return 0;
}

//********************************************
// OffsetToString
//********************************************
int CParserVrml::OffsetToString(char *string)
{
	while(m_IndexBuffer < m_SizeFile)
	{
		ReadLine();
		char *adr = strstr(m_pBufferLine,string);
		if(strstr(m_pBufferLine,string) != NULL)
		{
			m_IndexBuffer = m_IndexBuffer - strlen(m_pBufferLine) - 1 + (adr-m_pBufferLine);
			ASSERT(m_IndexBuffer >= 0);
			/*
			TRACE("  offset to string : %c%c%c%c%c... IndexBuffer : %d\n",m_pBuffer[m_IndexBuffer],
 				                                           m_pBuffer[m_IndexBuffer+1], 
				                                           m_pBuffer[m_IndexBuffer+2],
				                                           m_pBuffer[m_IndexBuffer+3],
																				           m_pBuffer[m_IndexBuffer+4],m_IndexBuffer);*/

			return 1;
		}
	}
	return 0;
}

//********************************************
// OffsetToString
//********************************************
int CParserVrml::OffsetToStringBefore(char *string,
																			char *before)
{
	while(m_IndexBuffer < m_SizeFile)
	{
		ReadLine();
		char *adr = strstr(m_pBufferLine,string);
		if(strstr(m_pBufferLine,before) != NULL)
			return 0;
		if(strstr(m_pBufferLine,string) != NULL)
		{
			m_IndexBuffer = m_IndexBuffer - strlen(m_pBufferLine) - 1 + (adr-m_pBufferLine);
			ASSERT(m_IndexBuffer >= 0);
			/*
			TRACE("  offset to string : %c%c%c%c%c... IndexBuffer : %d\n",m_pBuffer[m_IndexBuffer],
 				                                           m_pBuffer[m_IndexBuffer+1], 
				                                           m_pBuffer[m_IndexBuffer+2],
				                                           m_pBuffer[m_IndexBuffer+3],
																				           m_pBuffer[m_IndexBuffer+4],m_IndexBuffer);*/

			return 1;
		}
	}
	return 0;
}

//********************************************
// CheckMesh
//********************************************
int CParserVrml::CheckMesh()
{
	// Find a possible mesh
	TRACE("  check mesh...");
	OffsetToStringBeginLine("DEF");
	int tmp = m_IndexBuffer;
	ReadLine();
	if(strstr(m_pBufferLine,"DEF") != NULL && 
	   strstr(m_pBufferLine,"Transform") != NULL)
	{
		m_IndexBuffer = tmp;
		if(OffsetToString("Transform") &&
		   OffsetToString("Material") &&
		   OffsetToString("IndexedFaceSet"))
		{
			m_IndexBuffer = tmp;
			TRACE("ok\n");
			return 1;
		}
	}
	//m_IndexBuffer = tmp;
	TRACE("not a mesh\n");
	return 0;
}

//********************************************
// ReadMesh
//********************************************
int CParserVrml::ReadMesh(CSceneGraph3d *pSceneGraph)
{
	// Check
	if(!CheckMesh())
		return 0;

	int tmp = m_IndexBuffer;
	ReadLine();
	ASSERT(strstr(m_pBufferLine,"DEF") != NULL);
	ASSERT(strstr(m_pBufferLine,"Transform") != NULL);
	// DEF [name] Transform {
	if(sscanf(m_pBufferLine,"DEF %s Transform",m_pBufferWord) != 1)
	{
		TRACE("  invalid syntax (BufferLine : %s BufferWord : %s\n",m_pBufferLine,m_pBufferWord);
		return 0;
	}

	TRACE("  start reading mesh %s\n",m_pBufferWord);

	m_IndexBuffer = tmp;

	int IndexTexture = -1;

	// Transform
	//********************************************
	// Syntax :
	// Transform {
  // translation -360.7 1370 3471
  // rotation 0.3236 -0.3236 -0.8891 -1.688
  // scale -49.36 -49.36 -49.36
  // scaleOrientation -0.689 0.4766 -0.546 -0.6007

	OffsetToString("Transform");
	ReadLine(); // Transform
	CTransform transform;
	transform.Clear();

	// Translation
	tmp = m_IndexBuffer;
	ReadLine();
	if(strstr(m_pBufferLine,"translation") != NULL)
	{
		// Come back
		m_IndexBuffer = tmp;
		// Jump after "translation"
		ReadWord(); 

		float x,y,z;
		ReadWord();
		int success = sscanf(m_pBufferWord,"%f",&x);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%f",&y);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%f",&z);
		if(success)
		{
			transform.SetTranslation(CVector3d(x,y,z));
			TRACE("    translation : %g %g %g\n",x,y,z);
		}
		ReadLine();
		tmp = m_IndexBuffer;
		ReadLine();
	}

	// Rotation
	if(strstr(m_pBufferLine,"rotation") != NULL)
	{
		// Come back
		m_IndexBuffer = tmp;
		// Jump after "rotation"
		ReadWord(); 

		float x,y,z,value;
		ReadWord();
		int success = sscanf(m_pBufferWord,"%f",&x);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%f",&y);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%f",&z);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%f",&value);
		if(success)
		{
			transform.SetRotation(CVector3d(x,y,z));
			transform.SetValueRotation(value/3.1415926f*180.0f);
			TRACE("    rotation : %g %g %g %g\n",x,y,z,value);
		}
		ReadLine();
		tmp = m_IndexBuffer;
		ReadLine();
	}

	// Scale
	if(strstr(m_pBufferLine,"scale") != NULL)
	{
		// Come back
		m_IndexBuffer = tmp;
		// Jump after "scale"
		ReadWord(); 

		float x,y,z;
		ReadWord();
		int success = sscanf(m_pBufferWord,"%f",&x);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%f",&y);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%f",&z);
		if(success)
		{
			transform.SetScale(CVector3d(x,y,z));
			TRACE("    scale : %g %g %g\n",x,y,z);
		}
		ReadLine();
		tmp = m_IndexBuffer;
		ReadLine();
	}

	// ScaleOrientation
	if(strstr(m_pBufferLine,"scaleOrientation") != NULL)
	{
		// Come back
		m_IndexBuffer = tmp;
		// Jump after "scaleOrientation"
		ReadWord(); 

		float x,y,z,value;
		ReadWord();
		int success = sscanf(m_pBufferWord,"%f",&x);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%f",&y);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%f",&z);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%f",&value);
		if(success)
		{
			//transform.SetScale(CVector3d(x,y,z));
			TRACE("    scaleOrientation : %g %g %g %g\n",x,y,z,value);
		}
		ReadLine();
	}

	// Material
	//********************************************
	// appearance Appearance {
  // material Material {
  // diffuseColor 0.5686 0.1098 0.6941
	CMaterial material;
	if(OffsetToString("Material"))
	{
		ReadLine();

		tmp = m_IndexBuffer;

		// Diffuse color
		ReadLine(); 
		if(strstr(m_pBufferLine,"diffuseColor") != NULL)
		{
			// Come back
			m_IndexBuffer = tmp;

			// Jump
			ReadWord();

			float r,g,b;
			ReadWord();
			int success = sscanf(m_pBufferWord,"%f",&r);
			ReadWord();
			success &= sscanf(m_pBufferWord,"%f",&g);
			ReadWord();
			success &= sscanf(m_pBufferWord,"%f",&b);
			if(success)
			{
				material.SetDiffuse(r,g,b,1.0f);
				TRACE("    diffuseColor : %g %g %g\n",r,g,b);
			}
		}
	}

	// Texture
	//********************************************
	int texture = 0;
	if(OffsetToStringBefore("texture ImageTexture","geometry"))
	{
		texture = 1;
		ReadLine();
		tmp = m_IndexBuffer;

		ReadLine(); 
		if(strstr(m_pBufferLine,"url") != NULL)
		{
			// Come back
			m_IndexBuffer = tmp;

			// Jump
			ReadWord();
			char string[MAX_PATH];
			ReadWord();
			sscanf(m_pBufferWord,"%s",string);

			// Remove ""
			CString TextureName = string;
			TextureName = TextureName.Mid(1,TextureName.GetLength()-2);
			TRACE("    texture : %s\n",TextureName);

			// Ask SceneGraph to add texture, if needed
			char *name = TextureName.GetBuffer(MAX_PATH);
			if(!pSceneGraph->HasTexture(name,&IndexTexture))
			{
				CTexture *pTexture = new CTexture;
				pTexture->ReadFile(name);
				IndexTexture = pSceneGraph->AddTexture(pTexture);
			}
			TextureName.ReleaseBuffer();
		}
	}
	else // come back
		m_IndexBuffer = tmp;

	// Mesh
	//********************************************
	int NbVertex,NbFace,NbTextureCoordinate;
	// Count size (do not offset in file)
	if(!SizeMesh(&NbVertex,&NbFace,texture,&NbTextureCoordinate))
		return 0;

	// Add mesh
	CMesh3d *pMesh = new CMesh3d;
	pSceneGraph->Add(pMesh);
	// Set Size (faster)
	pMesh->m_ArrayVertex.SetSize(NbVertex);
	pMesh->m_ArrayFace.SetSize(NbFace);
	if(texture)
	{
		pMesh->m_pTextureCoordinate = new float[NbTextureCoordinate*2]; // x y 
		pMesh->m_pTextureCoordinateIndex = new int[NbFace*3];           // triangular faces
		pMesh->m_IndexTexture = IndexTexture;
	}
	// Store mesh (offset in file)
	StoreMesh(&pMesh->m_ArrayVertex,&pMesh->m_ArrayFace,texture,
		pMesh->m_pTextureCoordinate,pMesh->m_pTextureCoordinateIndex);

	// Transform & material
	pMesh->SetTransform(transform);
	pMesh->SetMaterial(&material);

	TRACE("  end reading mesh\n");

	return 1;
}

//********************************************
// SizeMesh
//********************************************
int CParserVrml::SizeMesh(int *pNbVertex,
													int *pNbFace,
													int HasTexture,
													int *pNbTextureCoordinate /* = NULL */)
{
	TRACE("    size mesh...");
	int tmp = m_IndexBuffer;

	ASSERT(pNbVertex != NULL);
	ASSERT(pNbFace != NULL);

	if(!OffsetToString("IndexedFaceSet"))
	{
		TRACE("invalid mesh\n");
		return 0;
	}

	// Count points
	//***********************************************
	if(!OffsetToString("Coordinate { point ["))
	{
		TRACE("invalid mesh\n");
		return 0;
	}

	m_IndexBuffer += strlen("Coordinate { point [") + 1;

	// Cur : x y z,
	// End : x y z]
	int NbVertex = 0;
	int success;
	do
	{
		float x,y,z;
		ReadWord();
		success = sscanf(m_pBufferWord,"%f",&x);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%f",&y);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%f",&z);
		NbVertex += success;
		//TRACE("\n (%g %g %g) ",x,y,z);
	}
	while(success);
	TRACE(" %d points,",NbVertex);

	if(NbVertex <= 0)
		return 0;


	// Count texture coordinates, if needed 
	//***********************************************
	int NbTextureCoordinate = 0;
	if(HasTexture)
	{
		if(!OffsetToString("TextureCoordinate { point ["))
		{
			TRACE("invalid texture coordinates\n");
			return 0;
		}

		m_IndexBuffer += strlen("TextureCoordinate { point [") + 1;

		// Cur : x y,
		// End : x y]
		int success;
		do
		{
			float x,y;
			ReadWord();
			success = sscanf(m_pBufferWord,"%f",&x);
			ReadWord();
			success &= sscanf(m_pBufferWord,"%f",&y);
			NbTextureCoordinate += success;
			//TRACE("\n (%g %g %g) ",x,y,z);
		}
		while(success);
		TRACE(" %d texture coordinates,",NbTextureCoordinate);

		if(NbTextureCoordinate <= 0)
			return 0;
	}


	// Count faces, accept only triangles
	//***********************************************
	m_IndexBuffer = tmp;
	if(!OffsetToString("coordIndex ["))
	{
		TRACE("invalid mesh\n");
		return 0;
	}
	m_IndexBuffer += strlen("coordIndex [") + 1;

	// Cur : int, int, int, -1,
	// End : int, int, int, -1]
	int NbFace = 0;
	do
	{
		int v1,v2,v3;
		ReadWord();
		success  = sscanf(m_pBufferWord,"%d,",&v1);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%d,",&v2);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%d,",&v3);
		NbFace += success;

		ASSERT(v1 >= 0);
		ASSERT(v2 >= 0);
		ASSERT(v3 >= 0);

		int test;
		ReadWord();
		sscanf(m_pBufferWord,"%d",&test);
		if(strstr(m_pBufferWord,"]") != NULL)
			success = 0;
	}
	while(success);
	TRACE(" %d faces,",NbFace);

	if(NbFace <= 0)
		return 0;

	// Count texture coordinate index 
	//***********************************************
	if(HasTexture)
	{
		m_IndexBuffer = tmp;
		if(!OffsetToString("texCoordIndex ["))
		{
			TRACE("invalid texture coordinate index\n");
			return 0;
		}
		m_IndexBuffer += strlen("texCoordIndex [") + 1;

		// Cur : int, int, int, -1,
		// End : int, int, int, -1]
		int NbCoordIndex = 0;
		do
		{
			int v1,v2,v3;
			ReadWord();
			success  = sscanf(m_pBufferWord,"%d,",&v1);
			ReadWord();
			success &= sscanf(m_pBufferWord,"%d,",&v2);
			ReadWord();
			success &= sscanf(m_pBufferWord,"%d,",&v3);
			NbCoordIndex += success;

			ASSERT(v1 >= 0);
			ASSERT(v2 >= 0);
			ASSERT(v3 >= 0);

			int test;
			ReadWord();
			sscanf(m_pBufferWord,"%d",&test);
			if(strstr(m_pBufferWord,"]") != NULL)
				success = 0;
		}
		while(success);
		TRACE(" %d coordinate index\n",NbCoordIndex);

		if(NbFace != NbCoordIndex)
		{
			TRACE(" different values for coord index and faces\n");
			return 0;
		}
	}

	// Store result
	*pNbVertex = NbVertex;
	*pNbFace = NbFace;
	if(HasTexture)
		*pNbTextureCoordinate = NbTextureCoordinate;

	m_IndexBuffer = tmp;

	return 1;
}


//********************************************
// StoreMesh
//********************************************
int CParserVrml::StoreMesh(CArray3d<CVertex3d> *pArrayVertex,
													 CArray3d<CFace3d> *pArrayFace,
													 int HasTexture,
													 float *pTextureCoordinate,
													 int *pTextureCoordinateIndex)
{
	TRACE("    store mesh...");
	int tmp = m_IndexBuffer;

	if(!OffsetToString("IndexedFaceSet"))
	{
		TRACE("invalid mesh\n");
		return 0;
	}

	// Store vertices
	//***********************************************
	if(!OffsetToString("Coordinate { point ["))
	{
		TRACE("invalid mesh\n");
		return 0;
	}
	m_IndexBuffer += strlen("Coordinate { point [") + 1;
	// Cur : x y z,
	// End : x y z]
	int success;
	int NbVertex = 0;
	do
	{
		float x,y,z;
		ReadWord();
		success = sscanf(m_pBufferWord,"%f",&x);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%f",&y);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%f",&z);
		if(success)
			pArrayVertex->SetAt(NbVertex++,new CVertex3d(x,y,z));
		//TRACE("\n (%g %g %g) ",x,y,z);
	}
	while(success);
	TRACE(" added %d vertices,",NbVertex);

	// Store texture coordinates (if needed)
	//***********************************************
	if(HasTexture)
	{
		if(!OffsetToString("TextureCoordinate { point ["))
		{
			TRACE("invalid texture coordinate\n");
			return 0;
		}
		m_IndexBuffer += strlen("TextureCoordinate { point [") + 1;
		// Cur : x y,
		// End : x y
		int success;
		int NbTextureCoordinate = 0;
		do
		{
			float x,y;
			ReadWord();
			success = sscanf(m_pBufferWord,"%f",&x);
			ReadWord();
			success &= sscanf(m_pBufferWord,"%f",&y);
			if(success)
			{
				pTextureCoordinate[2*NbTextureCoordinate] = x;
				pTextureCoordinate[2*NbTextureCoordinate+1] = y;
				NbTextureCoordinate++;
			}
			//TRACE("\n (%g %g) ",x,y);
		}
		while(success);
		TRACE(" added %d texture coordinates,",NbTextureCoordinate);
	}

	

	// Store faces, accept only triangles
	//***********************************************
	m_IndexBuffer = tmp;
	if(!OffsetToString("coordIndex ["))
	{
		TRACE("invalid mesh\n");
		return 0;
	}
	m_IndexBuffer += strlen("coordIndex [") + 1;

	// Cur : int, int, int, -1,
	// End : int, int, int, -1]
	int NbFace = 0;
	do
	{
		int v1,v2,v3;
		ReadWord();
		success  = sscanf(m_pBufferWord,"%d,",&v1);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%d,",&v2);
		ReadWord();
		success &= sscanf(m_pBufferWord,"%d,",&v3);

		ASSERT(v1 >= 0);
		ASSERT(v2 >= 0);
		ASSERT(v3 >= 0);


		if(success && v1 >= 0 && v2 >= 0 && v3 >= 0)
		{
			CFace3d *pFace = new CFace3d(pArrayVertex->GetAt(v1),
				                           pArrayVertex->GetAt(v2),
																	 pArrayVertex->GetAt(v3));
			pArrayFace->SetAt(NbFace++,pFace);
		}

		int test;
		ReadWord();
		sscanf(m_pBufferWord,"%d",&test);
		if(strstr(m_pBufferWord,"]") != NULL)
			success = 0;

	}
	while(success);
	TRACE(" added %d faces\n",NbFace);

	// Store texture coord index
	//***********************************************
	if(HasTexture)
	{
		m_IndexBuffer = tmp;
		if(!OffsetToString("texCoordIndex ["))
		{
			TRACE("invalid mesh\n");
			return 0;
		}
		m_IndexBuffer += strlen("texCoordIndex [") + 1;

		// Cur : int, int, int, -1,
		// End : int, int, int, -1]
		int NbTexCoordIndex = 0;
		do
		{
			int v1,v2,v3;
			ReadWord();
			success  = sscanf(m_pBufferWord,"%d,",&v1);
			ReadWord();
			success &= sscanf(m_pBufferWord,"%d,",&v2);
			ReadWord();
			success &= sscanf(m_pBufferWord,"%d,",&v3);

			ASSERT(v1 >= 0);
			ASSERT(v2 >= 0);
			ASSERT(v3 >= 0);

			if(success && v1 >= 0 && v2 >= 0 && v3 >= 0)
			{
				pTextureCoordinateIndex[3*NbTexCoordIndex] = v1;
				pTextureCoordinateIndex[3*NbTexCoordIndex+1] = v2;
				pTextureCoordinateIndex[3*NbTexCoordIndex+2] = v3;
				NbTexCoordIndex++;
			}

			int test;
			ReadWord();
			sscanf(m_pBufferWord,"%d",&test);
			if(strstr(m_pBufferWord,"]") != NULL)
				success = 0;

		}
		while(success);
		TRACE(" added %d texture coordinate index\n",NbTexCoordIndex);
	}

	return 1;
}

// ** EOF **